package fda.main;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import fda.base.Constants;
import fda.base.DiskFile;
import fda.base.IOCounter;
import fda.base.Memory;
import fda.base.Range;
import fda.base.Tuple;
import fda.merge.MergeEngine;
import fda.schema.Column;
import fda.schema.Schema;
import fda.schema.TableInfo;
import fda.sort.SortEngine;

public class Main {

	/**
	 * @param args
	 * Testing Committing from Faryed pc
	 * 
	 */
	public static void main(String[] args) {
		DiskFile.clearAllFiles(Constants.PRE_SUB); // delete all files in folder /sub when test starts
		System.out.print("\n---> Application Starts ...");
		
		/* container for sorted sublists */
		List<DiskFile> subLists = new LinkedList<DiskFile>();
		
		// Load data file
		TableInfo table = getDummyTableInfo();
		DiskFile source = new DiskFile(table);
		
		//////////////////////////////////////////////////////////
		// Phase 1 begin /////////////////////////////////////////
		//////////////////////////////////////////////////////////
		doSorting(subLists, source);
		
		//////////////////////////////////////////////////////////
		// Phase 2 Begin ////////////////////////////
		//////////////////////////////////////////////////////////
		doMerging(subLists);
		
		//////////////////////////////////////////////////////////
		// Phase 2 end ///////////////////////////////////////////
		//////////////////////////////////////////////////////////
		
		// highest entry contains result of all merges
		Range range = new Range(subLists.get(subLists.size() - 1));
		range.saveToFile(Constants.PRE_SUB + "range_table.txt");
		
		// print report about all operations
		IOCounter.getInst().printReport();
		//System.out.print("\n---> Application End.");
	}


	public static String doMerging(List<DiskFile> subLists) {
		MergeEngine merger = new MergeEngine(subLists.get(0).getTableInfo());
		merger.setMerge(subLists);
		return merger.merge();
	}

	
	/**
	 * @param subLists out parameter will be filled with sorted sublists
	 * @param source unsorted DiskFile
	 * @param mem Memory to sort in
	 */
	public static void doSorting(List<DiskFile> subLists, DiskFile source) {
		Tuple[] mem = Memory.getInstance().getMemory();
		SortEngine sortmem = new SortEngine(source.getTableInfo());
		List<Tuple> block = null;
		int index = 0;
		int fileID = 0;
		
		// Reads all blocks from source data file
		for (int i = 0; i < source.getBlockCount(); ++i) {
			block = source.getBlock(i);

			for (int ln = 0; ln < block.size(); ln++) {
				mem[index] = block.get(ln);
				index++;
			}

			if (index >= mem.length) { // when memory is filled, do sorting:

                mem = sortmem.sort(mem);
                 
				// save sorted mem[] for sublist
				DiskFile df = new DiskFile(Constants.PRE_SUB + fileID + ".txt", mem, source.getTableInfo(), true);
				fileID++;

				// keep sorted sublist
				subLists.add(df);
				
				// reset index
				index = 0;
			}
		}
		
		//write remaining tuples
		if(index > 0){
			Tuple[] remaining = Arrays.copyOfRange(mem, 0, index);
            sortmem.sort(remaining);
			DiskFile df = new DiskFile(Constants.PRE_SUB + fileID + ".txt", remaining, source.getTableInfo(), true);
			subLists.add(df);
		}
	}
	
	public static TableInfo getDummyTableInfo(){
		TableInfo ti = new TableInfo("files/datafile.txt", new Schema());
		ti.addCol(new Column("col1", 7));
		ti.addCol(new Column("col2", 16));
		ti.addCol(new Column("col3", 15));
		ti.addCol(new Column("col4", 8));
		ti.addCol(new Column("col5", 46));
		ti.setPrimeKeyIndex(0);
		return ti;
	}
	
	public static void log(String info){
		System.out.print("\n" + info);
	}
}
